﻿using System;
using SystemIO = System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Lucene.Net;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Store;
using Lucene.Net.Search;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;

namespace FTSearch
{
    public class Helper
    {
        public static TextBox TBFileIndexing
        {
            set;
            get;
        }

        public static DataGridView GVResults
        {
            get;
            set;
        }

        public static void Index(string path, string dbName)
        {
            Directory dir = FSDirectory.Open(SearchForm.INDEXDB_FOLDER + "\\" + dbName);
            Analyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
            IndexWriter writer = new IndexWriter(dir, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
            IndexDocs(writer, path);
            writer.Optimize();
            writer.Dispose();

        }

        private static void IndexDocs(IndexWriter writer, string path)
        {
            if (SystemIO.Directory.Exists(path))
            {
                SystemIO.DirectoryInfo dirInfo = new SystemIO.DirectoryInfo(path);
                foreach (SystemIO.FileInfo file in dirInfo.GetFiles())
                    IndexDocs(writer, file.FullName);
                foreach (SystemIO.DirectoryInfo dir in dirInfo.GetDirectories())
                    IndexDocs(writer, dir.FullName);
            }
            else
            {
                TBFileIndexing.AppendText(Environment.NewLine + path);
                string fileExt = SystemIO.Path.GetExtension(path);

                string extInclude = System.Configuration.ConfigurationManager.AppSettings["ExtInclude"];
                if (!string.IsNullOrEmpty(extInclude))
                {
                    if (!extInclude.Contains(fileExt))
                    {
                        TBFileIndexing.AppendText("... not include file extension - ignored");
                        return;
                    }
                }
                else
                {
                    string extExclude = System.Configuration.ConfigurationManager.AppSettings["ExtExclude"];

                    if (extExclude.Contains(fileExt))
                    {
                        TBFileIndexing.AppendText("... exclude file extension - ignored");
                        return;
                    }
                }
                SystemIO.FileInfo fileInfo = new System.IO.FileInfo(path);
                if (fileInfo.Length>10000000)//~10MB
                {
                    TBFileIndexing.AppendText("... big file - ignored");
                    return;
                }
                try
                {
                    Document doc = new Document();
                    Field pathField = new Field("path", path, Field.Store.YES, Field.Index.NO);
                    doc.Add(pathField);
                    doc.Add(new Field("modified",
                        new SystemIO.FileInfo(path).LastWriteTime.ToString("yyyyMMddHHmmss"), Field.Store.YES, Field.Index.NO));
                    Field contentField = new Field("content", SystemIO.File.ReadAllText(path), Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES);
                    doc.Add(contentField);
                    writer.AddDocument(doc);
                }
                catch (Exception ex)
                {
                    TBFileIndexing.AppendText("...read failed: " + ex.Message);
                }
            }
        }

        public static void Search(string term, string dbName)
        {
            Analyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);

            QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "content", analyzer);
            Query query = parser.Parse(term);

            Directory dir = FSDirectory.Open(SearchForm.INDEXDB_FOLDER + "\\" + dbName);
            Searcher searcher = new IndexSearcher(IndexReader.Open(dir, true));
            TopScoreDocCollector results = TopScoreDocCollector.Create(1000, true);
            searcher.Search(query, results);
            ScoreDoc[] hits = results.TopDocs().ScoreDocs;

            IList<ResultItem> resultList = new List<ResultItem>();

            for (int i = 0; i < hits.Length; i++)
            {
                int docId = hits[i].Doc;
                float score = hits[i].Score;

                Document doc = searcher.Doc(docId);
                string path = doc.Get("path");
                ResultItem item = new ResultItem();
                item.Path = path;
                item.Score = score.ToString();
                resultList.Add(item);
            }

            GVResults.DataSource = resultList;
        }

    }
}
